package com.boarsoft.boar.lib.biz;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.boar.dir.DirBiz;
import com.boarsoft.boar.entity.AppLib;
import com.boarsoft.boar.entity.DirInfo;
import com.boarsoft.boar.entity.LibInfo;
import com.boarsoft.boar.entity.SoaNexus;
import com.boarsoft.boar.lib.LibBiz;
import com.boarsoft.common.Util;
import com.boarsoft.common.dao.PagedResult;
import com.boarsoft.hibernate.biz.SimpleBizImpl;

public abstract class LibBizImpl extends SimpleBizImpl implements LibBiz {
	@Autowired
	protected DirBiz dirBiz;
	/** 由子类赋值 */
	protected Class<?> libInfoClazz;

	@Override
	@Transactional(readOnly = true)
	public LibInfo get(String id) {
		return (LibInfo) dao.get(libInfoClazz, id);
	}

	@Override
	@Transactional
	public ReplyInfo<Object> add(DirInfo d, LibInfo o) {
		dirBiz.add(d); // 保存DIR，有查重
		// 保存组件/服务，因为已在目录树中查了重，这里不需要再查
		o.setId(d.getId());// 以d的id作为o的id
		dao.save(o);
		return new ReplyInfo<Object>(true, d);
	}

	@Override
	@Transactional
	public ReplyInfo<Object> update(DirInfo d, LibInfo a) {
		if (d != null) {
			dirBiz.update(d);
		}
		dao.merge(a);
		return new ReplyInfo<Object>(true, d);
	}

	@Override
	@Transactional
	public void delete(String id) {
		// 删除库包信息，hibernate自动删除app_lib表相关数据
		dao.delete(libInfoClazz, id);
	}

	@Override
	@Transactional
	public void remove(String appId, String libId) {
		StringBuilder sql = new StringBuilder();
		sql.append("delete from ").append(AppLib.class.getName())//
				.append(" where lib.id = '").append(libId)//
				.append("' and app.id = '").append(appId).append("'");
		dao.executeUpdate(sql.toString());
	}

	@Override
	@Transactional
	public void start(String ids) {
		for (String x : ids.split(",")) {
			LibInfo o = (LibInfo) dao.get(libInfoClazz, x);
			o.setStatus(LibInfo.STATUS_INUSE);
			DirInfo d = (DirInfo) dao.get(DirInfo.class, x);
			d.setStatus(DirInfo.STATUS_INUSE);
		}
	}

	@Override
	@Transactional
	public void stop(String ids) {
		for (String x : ids.split(",")) {
			LibInfo o = (LibInfo) dao.get(libInfoClazz, x);
			o.setStatus(LibInfo.STATUS_NOUSE);
			DirInfo d = (DirInfo) dao.get(DirInfo.class, x);
			d.setStatus(DirInfo.STATUS_NOUSE);
		}
	}

	@Override
	@Transactional
	public String copy(String sourceId, String parentId, String newId) {
		LibInfo o = this.get(sourceId);
		LibInfo n = (LibInfo) this.transfer(o, libInfoClazz);
		n.setId(newId);// //应用的id来自于前一步骤的dir_info表id
		DirInfo pd = dirBiz.get(parentId);
		String projId = dirBiz.lookup(pd, DirInfo.TYPE_PROJ);
		n.setProjId(projId);
		dao.save(n);
		return newId;
	}

	/**
	 * 查询LIB被哪些项依赖
	 *
	 * @param id
	 *            LIB ID
	 * @return
	 */
	@Override
	@Transactional(readOnly = true)
	public List<SoaNexus> listOnMe(String id) {
		StringBuilder sb = new StringBuilder();
		// sb.append("select n from ").append(SoaNexus.class.getName());
		// sb.append(" n join fetch n.obj0 where n.objId1 in (");
		// sb.append("select d.id from DirInfo d where d.parentId='");
		// sb.append(id).append("')");
		sb.append("select n from ").append(SoaNexus.class.getName());
		sb.append(" n where n.objId1 = '").append(id).append("'");
		return dao.list(sb.toString());
	}

	/**
	 * 通过查询LIB下所有COM的被依赖项，来汇总依赖这个LIB的项
	 *
	 * @param id
	 *            LIB ID
	 * @return
	 */
	@Override
	@Transactional(readOnly = true)
	public List<SoaNexus> listByMe(String id) {
		StringBuilder sb = new StringBuilder();
		sb.append("select n from ").append(SoaNexus.class.getName());
		sb.append(" n join fetch n.obj1 where n.objId0 in (");
		sb.append("select d.id from DirInfo d where d.parentId='");
		sb.append(id).append("')");
		return dao.list(sb.toString());
	}

	@Override
	@Transactional(readOnly = true)
	public PagedResult<LibInfo> list(String projId, String key, String orderBy, int pageNo, int pageSize) {
		StringBuilder sb = new StringBuilder();
		if (Util.strIsNotEmpty(projId)) {
			DirInfo projDir = dao.get(DirInfo.class, projId);
			if ("/".equals(projDir.getPath())) {
				sb.append(" and exists (select id from DirInfo where type=").append(DirInfo.TYPE_LIB)
						.append(" and id=a.id and path like '").append(projDir.getPath()).append(projId).append("%'))");
			} else {
				sb.append(" and exists (select id from DirInfo where type=").append(DirInfo.TYPE_LIB)
						.append(" and id=a.id and path like '").append(projDir.getPath()).append("/").append(projId)
						.append("%'))");
			}
		} else {
			sb.append(")");
		}
		if (Util.strIsNotEmpty(key)) {
			sb.append(" and (a.code like '%").append(key);
			sb.append("%' or a.memo like '%").append(key);
			sb.append("%' or a.name like '%").append(key);
			sb.append("%')");
		}
		String totalSql = new StringBuilder().append("select count(a.id) from ")//
				.append(libInfoClazz.getName()).append(" a where EXISTS (select d.id from ")//
				.append(DirInfo.class.getName()).append(" d where d.id=a.id ")//
				.append(sb).toString();
		int total = dao.getTotal(totalSql);
		if (Util.strIsNotEmpty(orderBy)) {
			sb.append(" order by ").append(orderBy);
		} else {
			sb.append(" order by a.name");
		}
		String sql = new StringBuilder().append("select a from ").append(libInfoClazz.getName())
				.append(" a where EXISTS (select d.id from ").append(DirInfo.class.getName())//
				.append(" d where d.id=a.id ").append(sb).toString();
		List<LibInfo> lt = dao.list(sql, pageNo, pageSize);
		return new PagedResult<LibInfo>(total, lt, pageNo, pageSize);
	}

	@Override
	@Transactional(readOnly = true)
	public PagedResult<LibInfo> list(String projId, boolean in, String appId, String key, String orderBy, int pageNo,
			int pageSize) {
		StringBuilder sb = new StringBuilder();
		sb.append(" from ").append(libInfoClazz.getName());
		sb.append(" s where s.id not in (select a.libId from ")//
				.append(AppLib.class.getName()).append(" a where a.appId='")//
				.append(appId).append("')");
		if (Util.strIsNotEmpty(projId)) {
			sb.append(" and s.projId='").append(projId).append("'");
		}
		if (Util.strIsNotEmpty(key)) {
			sb.append(" and (s.code like '%").append(key);
			sb.append("%' or s.name like '%").append(key);
			sb.append("%' or s.memo like '%").append(key);
			sb.append("%')");
		}
		int total = dao.getTotal("select count(s.id)".concat(sb.toString()));
		if (Util.strIsNotEmpty(orderBy)) {
			String ob = Util.array2str(("s.".concat(orderBy))//
					.replaceAll(",", ",").split(","), ",");
			sb.append(" order by ").append(ob);
		} else {
			sb.append(" order by s.name");
		}
		List<LibInfo> lt = dao.list(//
				"select s from ".concat(sb.toString()), pageNo, pageSize);
		return new PagedResult<LibInfo>(total, lt, pageNo, pageSize);
	}
}